﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace Msngr
{
    public class Server
    {
        HashTable<String, User> connectedUsers;
        Thread listenThread;
        //[Command][Sender][To][Message]
        public Server()
        {
            connectedUsers = new HashTable<string,User>();
        }

        public bool Start(int port)
        {
            try
            {
                listenThread = new Thread(Listen);
                listenThread.Start(port);
            }
            catch (Exception e)
            {
                Log.WriteError("Server failed to start...");
                Log.WriteError(e.ToString());
                return false; 
            }
            return true;
        }

        public void Stop()
        {
            listenThread.Abort();
        }

        private void Listen(object port)
        {
            string hostName = Dns.GetHostName();
            byte[] inBytes;
            IPAddress ipAddress = Dns.GetHostEntry(hostName).AddressList[0];
            Socket listener = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                listener.Bind(new IPEndPoint(ipAddress, (int)port));
                listener.Listen(100);
                Log.WriteInfo("Server Started!");
                //Log.WriteInfo("Listening on [" + ipAddress.ToString().Substring(0, ipAddress.ToString().IndexOf("%")) + "]:" + port);
                Log.WriteInfo("Listening on [" + hostName + ":" + port + "]");
                while (true)
                {
                    inBytes = new Byte[1024];
                    int msgSize = listener.Accept().Receive(inBytes);
                    string data = Encoding.ASCII.GetString(inBytes, 0, msgSize);
                    ProcInData(data);
                }
            }
            catch (Exception e)
            {
                Log.WriteError("Server Error!!!");
                Log.WriteError(e.ToString());
            }
        }

        private void ProcInData(string data)
        {
            //TODO
        }

        private bool Connect(string userName, string passwordHash, IPEndPoint address)
        {
            if (!(ValidateUser(userName, passwordHash))) return false;  
            User tempUser = GetUserFromDB(userName, address);
            if (!(TestConnection(tempUser)))
            {
                Log.WriteError("Connection Failed[" + userName + "]");
                return false;
            }
            connectedUsers.Add(userName, tempUser);
            Log.WriteInfo(userName + " is now Connected!!!");
            return true;
        }

        private void HandleCMDInput()
        {
            //ToDO!!!
            string cmd = Console.ReadLine();
            HandleCMDInput();
        }

        private bool ValidateUser(string userName, string passwordHash)
        {
            //TODO
            return true;
        }

        private User GetUserFromDB(string userName, IPEndPoint address)
        {
            return new User(userName, Status.Online, address);
        }

        public string GetUserStatus(string userName)
        {
            //TODO
            return "Online";
        }

        private bool TestConnection(User user)
        {
            //TODO
            return true;
        }

        private void SendAll(string message)
        {
            //TODO
        }

        private void Send(User user, string message)
        {
            Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            byte[] outMessage = Encoding.ASCII.GetBytes(message);
        }
    }
}